﻿using CommunicationClass.Model;
using CommunicationClass.Server.Model;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections;
using static CommunicationClass.Server.Model.TcpServerDelegate;
using CommunicationClass.Client.Model;
using CommunicationClass.Auxiliary;
using static CommunicationClass.Model.SendReceiveEnum;
using System.Linq;

namespace CommunicationClass.Server
{
    public class ServerCommunication
    {
        /// <summary>
        /// Microsoft YaHei端口监听
        /// </summary>
        /// <param name="MaxConnect">监听客户端个数,默认99999999</param>
        /// <param name="TcpPort">开启的TCP端口号,默认7614</param>
        /// <param name="UdpPort">开启的TCP端口号,默认7615</param>
        public ServerCommunication(int MaxConnect= 99999999, int TcpPort= 7614,int UdpPort = 7615)
        {
            this.MaxConnect = MaxConnect;
            this.TcpPort = TcpPort;
            this.UdpPort = UdpPort;
        }
        /// <summary>
        /// TCP数据
        /// </summary>
        private byte[] TcpBuffer = new byte[MessageSendConfigure.MaxMessageTcpSendM * 1024 * 1024];
        /// <summary>
        /// UDP数据
        /// </summary>
        private byte[] UdpBuffer = new byte[MessageSendConfigure.MaxMessageUdpSendB];
        /// <summary>
        /// Tcp协议
        /// 创建一个新的Socket,这里我们使用最常用的基于Microsoft YaHei的Stream Socket（流式套接字） 
        /// </summary>
        private Socket TcpSocket;
        /// <summary>
        /// Udp协议
        /// </summary>
        private Socket UdpSocket;
        /// <summary>
        /// Udp 监听
        /// </summary>
        private Thread UdpReciveThread = null;
        /// <summary>
        /// 判断关闭和启动
        /// </summary>
        private bool IsScket = false;
        public enum JournalMessageEnum
        {
            登录=0,
            注销=1,
            注册=2,
            消息=3,
            错误=4,
            日志=5
        }

        /// <summary>
        /// 获取登录用户队列数
        /// </summary>
        public int UserInfoTheQueueCount
        {
            get
            {
                return _UserInfoTheQueueCount;
            }
        }
        /// <summary>
        /// 获取消息队列个数
        /// </summary>
        public int MessageTheQueueCount
        {
            get
            {
                return _MessageTheQueueCount;
            }
        }
        /// <summary>
        /// 等钱在线人数
        /// </summary>
        public int UserInfoCount
        {
            get
            {
                return ListUser.Count;
            }
        }
        /// <summary>
        /// 语音消息队列个数
        /// </summary>
        public int VoiceMessageTheQueueCount
        {
            get { return _VoiceMessageTheQueueCount; }
        }
        /// <summary>
        /// 图片消息队列个数
        /// </summary>
        public int ImageMessageTheQueueCount
        {
            get
            {
                return _ImageMessageTheQueueCount;
            }
        }
        /// <summary>
        /// 短视频消息队列个数
        /// </summary>
        public int ShortVideoTheQueueCount
        {
            get
            {
                return _ShortVideoTheQueueCount;
            }
        }
        /// <summary>
        /// 监听客户端个数
        /// </summary>
        private int MaxConnect=99999999;
        /// <summary>
        /// TCP端口号
        /// </summary>
        private int TcpPort = 7614;
        /// <summary>
        /// Udp端口号
        /// </summary>
        private int UdpPort = 7615;
        /// <summary>
        /// 日志信息,需自行转换UI线程
        /// </summary>
        public event DelegateJournalMessage JournalMessage;
        /// <summary>
        /// 用户登录事件,UI操作需自行转换UI线程
        /// </summary>
        public event DelegateServerLogin ServerLogin;
        /// <summary>
        /// 接收消息回调事件,数据库操作推荐异步消息队列解决耗时,UI操作需自行转换UI线程
        /// </summary>
        public event DelegateServerReceiveMessage ServerReceiveMessage;
        /// <summary>
        /// 用户登录加载基本信息 UI操作需自行转换UI线程
        /// </summary>
        public event DelegateLoadData LoadUserData;
        /// <summary>
        /// 登录Socket信息关联
        /// </summary>
        private Hashtable  ListUser = new Hashtable();
        /// <summary>
        /// 普通消息队列个数
        /// </summary>
        private int _MessageTheQueueCount = 0;
        /// <summary>
        /// 语音消息队列个数
        /// </summary>
        private int _VoiceMessageTheQueueCount = 0;
        /// <summary>
        /// 图片消息队列个数
        /// </summary>
        private int _ImageMessageTheQueueCount = 0;
        /// <summary>
        /// 用户登录队列个数
        /// </summary>
        private  int _UserInfoTheQueueCount = 0;
        /// <summary>
        /// 短视频队列个数
        /// </summary>
        private int _ShortVideoTheQueueCount = 0;
        /// <summary>
        /// 登录用户
        /// </summary>
        /// <param name="UserInfo">登录用户信息</param>
        /// <param name="Message">异常信息，登录成功无异常信息，否则返回异常信息</param>
        /// <returns>是否登录成功</returns>
        private bool LockHashtableLogin(ref SocketListOnline SocketListOnline, ref string Message)
        {
            
            if (SocketListOnline == null ||  SocketListOnline.UserLogin==null || SocketListOnline.TcpClient == null ||
                string.IsNullOrEmpty(SocketListOnline.UserLogin.MsgLoginUserID) || string.IsNullOrEmpty(SocketListOnline.UserLogin.Pwd))
            {
                Message = "传递数据错误！";
                return false;
            }
            Interlocked.Increment(ref _UserInfoTheQueueCount);
            try
            {
                //异常信息
                Message = string.Empty;
                //登录
                if (ServerLogin != null)
                {
                    string UserName = "";
                    if (ServerLogin(SocketListOnline.UserLogin.MsgLoginUserID, SocketListOnline.UserLogin.Pwd, SocketListOnline.UserLogin.MsgLoginType, out UserName, out Message))
                    {
                        SocketListOnline.UserLogin.MsgLoginUserName = UserName;
                        Message = string.Empty;
                    }
                    else
                    {
                        Message = $"登录{SocketListOnline.UserLogin.MsgLoginUserID}失败，原因：" + Message;
                        JournalMessage?.BeginInvoke(JournalMessageEnum.日志, Message, null, null);
                    }
                }

                if (string.IsNullOrEmpty(Message))
                {

                    //判断用户是否在线
                    if (GetUserInfoAndSocket(SocketListOnline.UserLogin.MsgLoginUserID, SocketListOnline.UserLogin.MsgLoginType) == null)
                    {
                        string Key = SocketListOnline.UserLogin.MsgLoginIp.Replace(".", "") + SocketListOnline.UserLogin.MsgLoginPort;
                        bool IsIpAndPort = false;//在外面声明 减少同步锁时间
                        lock (ListUser.SyncRoot)
                        {
                            //判断当前电脑当前端口号是否被其他用户占用
                            if (!ListUser.ContainsKey(Key))
                            {
                                //添加登录用户数据
                                ListUser.Add(Key, SocketListOnline);
                            }
                            else
                            {
                                IsIpAndPort = true;
                            }
                        }

                        if (IsIpAndPort)
                        {
                            Message = $"{SocketListOnline.UserLogin.MsgLoginUserName}({SocketListOnline.UserLogin.MsgLoginUserID})用户登录失败！登录设备：{SocketListOnline.UserLogin.MsgLoginType},登录时间{DateTime.Now.ToString()},原因：当前电脑端口号正在被其他账户占用！";
                        }

                    }
                    else
                    {
                        Message = $"{SocketListOnline.UserLogin.MsgLoginUserName}({SocketListOnline.UserLogin.MsgLoginUserID})用户登录失败！登录设备：{SocketListOnline.UserLogin.MsgLoginType},登录时间{DateTime.Now.ToString()},原因：已经登录,无法再次登录！";
                    }

                }
                //减去队列数
            }
            catch (Exception ex)
            {
                JournalMessage?.BeginInvoke(JournalMessageEnum.错误, "用户登录方法LockHashtableLogin错误：" + ex.Message, null, null);

            }
            Interlocked.Decrement(ref _UserInfoTheQueueCount); 
            //当前队列添加完毕
            return string.IsNullOrEmpty(Message) ?true:false;
        }

        /// <summary>
        /// 获取用户登录信息
        /// </summary>
        /// <param name="UserID">用户ID</param>
        /// <param name="loginType">登录设备</param>
        /// <param name="IsSyncRoot">是否同步，默认同步</param>
        /// <returns></returns>
        private SocketListOnline GetUserInfoAndSocket(string UserID, MsgLoginTypeEnum loginType,bool IsSyncRoot=true)
        {
            if (IsSyncRoot)
            {
                //同步获取
                lock (ListUser.SyncRoot)
                {
                    //遍历数据
                    foreach (SocketListOnline item in ListUser.Values)
                    {
                        if (item.UserLogin.MsgLoginUserID == UserID && item.UserLogin.MsgLoginType == loginType)
                        {
                            //用户在线
                            return item;
                        }
                    }
                }
            }
            else
            {   //遍历数据
                foreach (SocketListOnline item in ListUser.Values)
                {
                    if (item.UserLogin.MsgLoginUserID == UserID && item.UserLogin.MsgLoginType == loginType)
                    {
                        //用户在线
                        return item;
                    }
                }

            }

            return null;

        }



        /// <summary>
        /// 开启监听端口
        /// </summary>
        /// <param name="message">开启状态信息</param>
        /// <returns></returns>
        public bool Open(out string message)
        {
            bool IsSuccess = true;
            string MessageOut = "";
            try
            {
                if (TcpSocket==null)
                {
                    TcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    //将该socket绑定到主机上面的某个端口
                    TcpSocket.Bind(new IPEndPoint(IPAddress.Any, TcpPort));
                    //启动监听，并且设置一个最大的队列长度
                    TcpSocket.Listen(MaxConnect);
                    //判断是否关闭监听
                    IsScket = true;
                    //开始接受客户端连接请求
                    TcpSocket.BeginAccept(new AsyncCallback(ClientAccepted), TcpSocket);
                    MessageOut += "开启消息" + TcpPort.ToString() + "端口监听成功!";
                }

            }
            catch (Exception ex)
            {
                IsSuccess = false;
                TcpSocket = null;
                MessageOut += "开启消息" + TcpPort.ToString() + "端口监听失败！原因如下：\r\n" + ex.Message;
            }

            try
            {
                if (UdpSocket==null)
                {
                    //建立Udp
                    UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    //绑定监听端口
                    UdpSocket.Bind(new IPEndPoint(IPAddress.Any, UdpPort));
                    if (UdpReciveThread!=null)
                    {
                        try
                        {
                            UdpReciveThread.Abort();
                        }
                        catch (Exception)
                        {

                        }
                       
                    }
                        UdpReciveThread = new Thread(UdpReciveMsg);
                        UdpReciveThread.IsBackground = true;
                        UdpReciveThread.Start();
                   
                    MessageOut += "开启打洞UDP：" + UdpPort.ToString() + "端口监听成功!";
                }
              
            }
            catch (Exception ex)
            {
                IsSuccess = false;
                MessageOut += "开启打洞UDP：" + UdpPort.ToString() + "端口监听失败！原因如下：\r\n" + ex.Message;

                if (TcpSocket!=null)
                {
                    TcpSocket.Close();
                    IsScket = false;

                }
            }
            message = MessageOut;
            return IsSuccess;

        }
        /// <summary>
        /// 接收发送给本机ip对应端口号的数据报
        /// </summary>
        private void UdpReciveMsg()
        {
            while (true)
            {
                try
                {
                    EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
                    int length = UdpSocket.ReceiveFrom(UdpBuffer, ref point);//接收数据报

                    if (length > 0)
                    {
                        //取数据
                        string UserKey = JsonHelper.JsonDateDeserialize<string>(UdpBuffer.Take(length).ToArray());
                        if (ListUser[UserKey] != null)
                        {
                            SocketListOnline UserInfo = ListUser[UserKey] as SocketListOnline;
                            if (string.IsNullOrEmpty(UserInfo.UdpHost))
                            {
                                UserInfo.UdpHost = ((System.Net.IPEndPoint)point).Address.ToString();
                                UserInfo.UdpPort = ((System.Net.IPEndPoint)point).Port;
                            }
                            else
                            {
                                //非法请求
                            }
                        }
                    }
                }
                catch (Exception)
                {

                   
                }




            }
        }

             
        /// <summary>
        /// 关闭监听端口
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool Close(out string message)
        {
            bool IsSuccess = true;
            string MessageOut = "";
            try
            {
                if (TcpSocket!=null)
                {
                    IsScket = false;
                    TcpSocket.Close();
                    TcpSocket = null;
                    lock (ListUser.SyncRoot)
                    {
                        ListUser.Clear();
                    }

                    MessageOut += "关闭消息TCP:" + TcpPort.ToString() + "端口成功!";
                }

                
            }
            catch (Exception ex)
            {
                MessageOut += "关闭消息TCP:" + TcpPort.ToString() + "端口失败！原因如下：\r\n" + ex.Message;
                IsSuccess = false;
            }

            try
            {
                if (UdpSocket!=null)
                {
                    UdpSocket.Close();
                }

                MessageOut+= "关闭消息UDP:" + TcpPort.ToString() + "端口成功!";
            }
            catch (Exception ex)
            {
                MessageOut+= "关闭消息UDP:" + TcpPort.ToString() + "端口失败！原因如下：\r\n" + ex.Message;
                IsSuccess = false;
            }
            message = MessageOut;
            return IsSuccess;
        }
        private  void ClientAccepted(IAsyncResult ar)
        {
            try
            {
                var socket = ar.AsyncState as Socket;
                //这就是客户端的Socket实例，我们后续可以将其保存起来
                var client = socket.EndAccept(ar);
                //实现每隔5秒钟判断用户是否下线
                string clientname = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address.ToString().Replace(".", "") + ((System.Net.IPEndPoint)client.RemoteEndPoint).Port;
                var timer = new System.Timers.Timer();
                timer.Interval = 5000;
                timer.Enabled = true;
                timer.Elapsed += (o, a) =>
                {
                    //检测客户端Socket的状态
                    if (!client.Connected)
                    {
                        try
                        {
                            //用户下线操作
                            lock (ListUser.SyncRoot)
                            {
                                if (ListUser.Contains(clientname))
                                {
                                    MessageUserLogin userinfo = ((SocketListOnline)ListUser[clientname]).UserLogin;
                                    JournalMessage?.BeginInvoke(JournalMessageEnum.注销, userinfo.MsgLoginUserName + "(" + userinfo.MsgLoginUserID + ")用户,注销登录！",null,null);
                                    ListUser.Remove(clientname);
                                }
                            }
                            //空数据

                            timer.Stop();
                            timer.Enabled = false;

                        }
                        catch (Exception ex)
                        {
                            JournalMessage?.BeginInvoke(JournalMessageEnum.错误, "时钟注销用户错误："+ex.Message, null, null);
                        }
                    }

                };
                timer.Start();

                //接收客户端的消息(这个和在客户端实现的方式是一样的）
                client.BeginReceive(TcpBuffer, 0, TcpBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client);

                //准备接受下一个客户端请求
                socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
            }
            catch (Exception ex)
            {
                //服务关闭
                JournalMessage?.BeginInvoke(JournalMessageEnum.错误, "建立连接错误,可能关闭了服务，导致接收下一条连接错误："+ex.Message, null, null);
            }
        }



        private void ReceiveMessage(IAsyncResult ar)
        {

            try
            {
                var socket = ar.AsyncState as Socket;
                var length = socket.EndReceive(ar);
                if (!IsScket && socket.Connected)
                {
                    socket.Close();
                }
                if (TcpBuffer != null && TcpBuffer.Length>0)
                {
                    try
                    {
                        
                        string UserKey = ((System.Net.IPEndPoint)socket.RemoteEndPoint).Address.ToString().Replace(".", "") + ((System.Net.IPEndPoint)socket.RemoteEndPoint).Port.ToString();
                        List<SendModel> ListSendModel = ReceiveLengthCalculation.ReceiveMessageCalculation<SendModel>(TcpBuffer, length);
                        //处理数据
                        foreach (SendModel sendModel in ListSendModel)
                        {

                            if (sendModel.SendTypeEnum == SendOrReceiveTypeEnum.登录)
                            {
                                string ReceiveContent =  Encoding.Unicode.GetString(sendModel.Data);
                                string UserID = ReceiveContent.Substring(0, ReceiveContent.Length - 33);
                                string Pwd = ReceiveContent.Substring(ReceiveContent.Length - 33, 32);
                                string type = ReceiveContent.Substring(ReceiveContent.Length - 1, 1);

                                //入库
                                MessageUserLogin login = new MessageUserLogin();
                                login.MsgLoginUserID = UserID;
                                login.MsgLoginUserName = "匿名";
                                MsgLoginTypeEnum msglogin = (MsgLoginTypeEnum)int.Parse(type);
                                login.MsgLoginType = msglogin;
                                login.MsgLoginIp = ((System.Net.IPEndPoint)socket.RemoteEndPoint).Address.ToString();
                                login.MsgLoginPort = ((System.Net.IPEndPoint)socket.RemoteEndPoint).Port;
                                login.Pwd = Pwd;
                                string StrSend = string.Empty;
                                ReceiveModel receive = new ReceiveModel();

                                SocketListOnline listOnline = new SocketListOnline()
                                {
                                    TcpClient = socket,
                                    UserLogin = login
                                };

                                if (LockHashtableLogin(ref listOnline, ref StrSend))
                                {
                                    //登录成功
                                    string Welcome = "欢迎" + login.MsgLoginUserName + "(" + UserID + ")登录成功！登录设备：" + msglogin + "登录时间：" + DateTime.Now.ToString();
                                    string[] StrList = new string[]
                                    {
                                         Welcome,
                                         LoadUserData?.Invoke(login),
                                         //将用户唯一标识发送回去
                                         UserKey
                                    };

                                    StrSend = JsonHelper.JsonDateSerializerString<string[]>(StrList);
                                    JournalMessage?.BeginInvoke(JournalMessageEnum.登录, Welcome, null, null);
                                    receive.IsSuccess = true;
                                }
                                else
                                {
                                    receive.IsSuccess = false;
                                    //登录失败
                                }
                                receive.Data = StrSend;


                                //发送数据 需要处理
                                SendModel sendModel1 = new SendModel()
                                {
                                    SendTypeEnum = SendOrReceiveTypeEnum.登录答应
                                };

                                //消息数据
                                sendModel1.Data = JsonHelper.JsonDateSerializer<ReceiveModel>(receive);

                                //转换发送消息
                                byte[] outputBuffer = SendLengthCalculation.SendJsonConvert(sendModel1);

                                socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null);

                            }
                            else if (sendModel.SendTypeEnum == SendOrReceiveTypeEnum.注册)
                            {

                            }
                            else
                            {
                                //判断用户是否登录
                                if (ListUser.Contains(UserKey))
                                {
                                    //获取用户登录信息
                                    SocketListOnline UserInfo = ListUser[UserKey] as SocketListOnline;
                                    switch (sendModel.SendTypeEnum)
                                    {
                                        case SendOrReceiveTypeEnum.普通消息:
                                            {
                                                Interlocked.Increment(ref _MessageTheQueueCount);
                                                MessageToTurnTo(socket, sendModel);
                                                Interlocked.Decrement(ref _MessageTheQueueCount);
                                                break;
                                            }
                                        case SendOrReceiveTypeEnum.语音消息:
                                            {
                                                Interlocked.Increment(ref _VoiceMessageTheQueueCount);
                                                MessageToTurnTo(socket, sendModel);
                                                Interlocked.Decrement(ref _VoiceMessageTheQueueCount);
                                                break;
                                            }
                                        case SendOrReceiveTypeEnum.图片:
                                            {
                                                Interlocked.Increment(ref _ImageMessageTheQueueCount);
                                                MessageToTurnTo(socket, sendModel);
                                                Interlocked.Decrement(ref _ImageMessageTheQueueCount);
                                                break;
                                            }
                                        case SendOrReceiveTypeEnum.短视频:
                                            {
                                                Interlocked.Increment(ref _ShortVideoTheQueueCount);
                                                MessageToTurnTo(socket, sendModel);
                                                Interlocked.Decrement(ref _ShortVideoTheQueueCount);
                                                break;
                                            }
                                        case SendOrReceiveTypeEnum.用户打洞:
                                            {
                                                
                                                UserConnectHole userConnectHole = Auxiliary.JsonHelper.JsonDateDeserialize<UserConnectHole>(sendModel.Data);
                                                //获取用户是否在线

                                                SocketListOnline messageUserLogin = null;
                                                foreach (MsgLoginTypeEnum item in Enum.GetValues(typeof(MsgLoginTypeEnum)))
                                                {
                                                    messageUserLogin = GetUserInfoAndSocket(userConnectHole.ReceiveUserID, item);
                                                    if (messageUserLogin!=null)
                                                    {
                                                        break;
                                                    }
                                                }

                                                if (messageUserLogin != null)
                                                {
                                                    //发送第一个用户在线的设备，用于传输文件和语音通话视频通话
                                                    userConnectHole.SendIp = UserInfo.UdpHost;
                                                    userConnectHole.SendPort = UserInfo.UdpPort;
                                                    userConnectHole.SendUserID = UserInfo.UserLogin.MsgLoginUserID;
                                                    messageUserLogin.TcpClient.BeginSend(sendModel.Data, 0, sendModel.Data.Length, SocketFlags.None, null, null);
                                                }
                                                else
                                                {
                                                    //用户不在线
                                                }
                                                    break;
                                            }
                                        case SendOrReceiveTypeEnum.注销:
                                            {
                                                lock (ListUser.SyncRoot)
                                                {
                                                    if (ListUser.Contains(UserKey))
                                                    {
                                                        MessageUserLogin userinfo = ((SocketListOnline)ListUser[UserKey]).UserLogin;
                                                        JournalMessage?.BeginInvoke(JournalMessageEnum.注销, userinfo.MsgLoginUserName + "(" + userinfo.MsgLoginUserID + ")用户,注销登录！", null, null);
                                                        ListUser.Remove(UserKey);
                                                    }
                                                }
                                                break;
                                            }
                                        default:
                                            break;
                                    }
                                }
                                else
                                {
                                    //未登录
                                    SendModel sendModel1 = new SendModel();
                                    sendModel1.SendTypeEnum = SendOrReceiveTypeEnum.未登录;
                                    ReceiveModel receive = new ReceiveModel();
                                    receive.IsSuccess = false;
                                    receive.Data = "未登录，非法调用！";
                                    sendModel1.Data = JsonHelper.JsonDateSerializer<ReceiveModel>(receive);
                                    byte[] outputBuffer = SendLengthCalculation.SendJsonConvert(sendModel1);
                                    socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null);

                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        JournalMessage?.BeginInvoke(JournalMessageEnum.错误, "数据异常，可能存在丢包，错误详细："+ex.Message,null,null);
                        //数据转换异常

                    }

                }
                //接收下一个消息(因为这是一个递归的调用，所以这样就可以一直接收消息了）
                socket.BeginReceive(TcpBuffer, 0, TcpBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);

            }
            catch (Exception ex)
            {
                //断开连接或其他错误，无法通讯
                //JournalMessage?.BeginInvoke(JournalMessageEnum.错误, "断开连接或其他错误，无法通讯,详细错误：" + ex.Message, null, null);
            }


        }
        /// <summary>
        /// 语音消息，短视频，普通消息，图片消息 的 消息转向
        /// </summary>
        /// <param name="socket">当前用户通讯</param>
        /// <param name="sendModel">发送的消息</param>
        private void MessageToTurnTo(Socket socket, SendModel sendModel)
        {
            try
            {

                MessageModel messageModel = Auxiliary.JsonHelper.JsonDateDeserialize<MessageModel>(sendModel.Data);
                string OutReceiveMessage = "";
                bool? IsServerReceiveMessage = ServerReceiveMessage?.Invoke(messageModel, sendModel.SendTypeEnum, out OutReceiveMessage);
                //用于响应消息发送是否成功详细数据
                ReceiveModel receive = new ReceiveModel();

                //发送消息
                SendModel sendModel1 = new SendModel();
                if (IsServerReceiveMessage == true || IsServerReceiveMessage == null)
                {
                    //循环消息要发送的设备
                    if (messageModel.MsgSendeQuipment != null)
                    {
                        foreach (MsgLoginTypeEnum item in messageModel.MsgSendeQuipment)
                        {
                            //发送的设备的用户是否在线
                            SocketListOnline messageUserLogin = GetUserInfoAndSocket(messageModel.MsgReceiveUserID, item);
                            if (messageUserLogin != null)
                            {
                                //发送消息
                                //string json = CommunicationClass.Auxiliary.JsonHelper.JsonDateSerializer<MessageModel>(messageModel);

                                receive.IsSuccess = true;
                                receive.Data = messageModel.MsgID;
                                //响应消息
                                sendModel1.SendTypeEnum = sendModel.SendTypeEnum;// SendOrReceiveTypeEnum.普通消息;
                                //消息数据
                                sendModel1.Data = JsonHelper.JsonDateSerializer<MessageModel>(messageModel);
                                //转换发送消息
                                byte[] outputBuffer1 = SendLengthCalculation.SendJsonConvert(sendModel1);

                                try
                                {
                                    messageUserLogin.TcpClient.BeginSend(outputBuffer1, 0, outputBuffer1.Length, SocketFlags.None, null, null);
                                }
                                catch (Exception ex)
                                {
                                    //用户已经离线
                                }
                               
                            }
                        }

                    }
                    receive.IsSuccess = true;
                    receive.Data = messageModel.MsgID;
                }
                else
                {
                    receive.IsSuccess = false;
                    receive.Data = OutReceiveMessage;

                }

                //响应消息
                sendModel1.SendTypeEnum = GetCorresponding(sendModel.SendTypeEnum);
                //消息数据
                sendModel1.Data = JsonHelper.JsonDateSerializer<ReceiveModel>(receive);
                //转换发送消息
                byte[] outputBuffer = SendLengthCalculation.SendJsonConvert(sendModel1);

                socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null);
            }
            catch (Exception ex)
            {
                JournalMessage?.BeginInvoke(JournalMessageEnum.错误, sendModel.SendTypeEnum.ToString()+"消息错误：" + ex.Message, null, null);

            }
        }
    }
}
